﻿using Microsoft.EntityFrameworkCore;

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SRM.Core.Repositories;

namespace SRM.DataAccess.Repositories
{
    public class RepositoryBase<TEtity> : IRepository<TEtity> where TEtity : class
    {
        /// <summary>
        /// 数据库上下文
        /// </summary>
        protected readonly AppDbContext _dbcontext;

        public RepositoryBase(AppDbContext dbcontext)
        {
            _dbcontext = dbcontext;
        }

        public virtual DbSet<TEtity> Table => _dbcontext.Set<TEtity>();

        #region 实体的增删改查

        public IQueryable<TEtity> GetAll()
        {
            return Table.AsQueryable();
        }

        public List<TEtity> GetAllList()
        {
            return GetAll().ToList();
        }

        public async Task<List<TEtity>> GetAllListAsync()
        {
            return await GetAll().ToListAsync();
        }

        public List<TEtity> GetAllList(Expression<Func<TEtity, bool>> expression)
        {
            return GetAll().Where(expression).ToList();
        }

        public async Task<List<TEtity>> GetAllListAsync(Expression<Func<TEtity, bool>> expression)
        {
            return await GetAll().Where(expression).ToListAsync();
        }

        public TEtity Single(Expression<Func<TEtity, bool>> expression)
        {
            return GetAll().Single(expression);
        }

        public async Task<TEtity> SingleAsync(Expression<Func<TEtity, bool>> expression)
        {
            return await GetAll().SingleAsync(expression);
        }

        public TEtity FirstOrDefault(Expression<Func<TEtity, bool>> expression)
        {
            return GetAll().FirstOrDefault(expression);
        }

        public async Task<TEtity> FirstOrDefaultAsync(Expression<Func<TEtity, bool>> expression)
        {
            var entity = await GetAll().FirstOrDefaultAsync(expression);
            return entity;
        }

        public TEtity Insert(TEtity entity)
        {
            var newentity = Table.Add(entity).Entity;
            Save();
            return newentity;
        }

        public async Task<TEtity> InsertAsync(TEtity entity)
        {
            var newentity = await Table.AddAsync(entity);
            await SaveAsync();
            return newentity.Entity;
        }

        public TEtity Update(TEtity entity)
        {
            AttachIfNot(entity);
            _dbcontext.Entry(entity).State = EntityState.Modified;
            Save();
            return entity;
        }

        public async Task<TEtity> UpdateAsync(TEtity entity)
        {
            AttachIfNot(entity);
            _dbcontext.Entry(entity).State = EntityState.Modified;
            await SaveAsync();
            return entity;
        }

        public void Delete(TEtity entity)
        {
            AttachIfNot(entity);
            Table.Remove(entity);
            Save();
        }

        public async Task DeleteAsync(TEtity entity)
        {
            AttachIfNot(entity);
            Table.Remove(entity);
            await SaveAsync();
        }

        public void Delete(Expression<Func<TEtity, bool>> expression)
        {
            foreach (var etity in GetAll().Where(expression).ToList())
            {
                Delete(etity);
            }
        }

        public async Task DeleteAsync(Expression<Func<TEtity, bool>> expression)
        {
            foreach (var etity in GetAll().Where(expression).ToList())
            {
                await DeleteAsync(etity);
            }
        }

        protected virtual void AttachIfNot(TEtity etity)
        {
            var entry = _dbcontext.ChangeTracker.Entries().FirstOrDefault(ent => ent.Entity == etity);
            if (entry != null)
            {
                return;
            }

            Table.Attach(etity);
        }

        protected void Save()
        {
            _dbcontext.SaveChanges();
        }

        protected async Task SaveAsync()
        {
            await _dbcontext.SaveChangesAsync();
        }

        #endregion 实体的增删改查

        public int Count()
        {
            return GetAll().Count();
        }

        public async Task<int> CountAsync()
        {
            return await GetAll().CountAsync();
        }

        public int Count(Expression<Func<TEtity, bool>> expression)
        {
            return GetAll().Where(expression).Count();
        }

        public async Task<int> CountAsync(Expression<Func<TEtity, bool>> expression)
        {
            return await GetAll().Where(expression).CountAsync();
        }

        public long LongCount()
        {
            return GetAll().LongCount();
        }

        public async Task<long> LongCountAsync()
        {
            return await GetAll().LongCountAsync();
        }

        public long LongCount(Expression<Func<TEtity, bool>> expression)
        {
            return GetAll().Where(expression).LongCount();
        }

        public async Task<long> LongCountAsync(Expression<Func<TEtity, bool>> expression)
        {
            return await GetAll().Where(expression).LongCountAsync();
        }
    }
}
